home *** CD-ROM | disk | FTP | other *** search
- /* UNIX like GETTY program. Kees Lemmens; Aug '92
-
- This program provides a way to start a shell on a remote line
- such as a modem.
- It can be run on an ATARI without MINT multitasking kernel, but
- only with MINT you'll be able to run on the background !
- If you're not using MINT you also have to recompile with new pathnames
- for "wtmp", "passwd", other signal handling (predefined in this source)
- and with an empty "devpath" .
-
- Features:
-
- - Can handle (Hayes) modem lines as well as hardwired terminals.
- - Redirects in and output to any line (or pipe) specified in <tty>.
- - Searches the username in the passwordfile and determines from
- there the SHELL and the (encrypted) PWD.
- - Suppresses echo while entering the password.
- - If the user is found and the password is alright it starts the program
- defined in SHELL. It restores the login prompt after the shell has
- finished on a direct line, a modemline receives a hangup.
- - Writes a log entry in (UNIX-like) UTMP and WTMP files to see who logged
- in where and when. WTMP logging is only used if there's is already an
- existing (empty ?) WTMP file.
- The same applies for a BTMP file, where bad logins will be logged.
- UTMP will be created if it does not exist.
- - Puts the username and home directory in the environment as variables
- LOGNAME and HOME. Also TTYNAME and an initial PATH variable is set.
- - The getty program aborts when a modemline does not respond with "OK"
- when the program sends an initial reset to the modem (ATZ).
- - Can also be run in background mode with the -d option (only MINT !)
- - Number of rings before answering the modemline can be adjusted by
- the -r option. (default after 1 ring)
-
- Known Bugs:
-
- - The baudrate can only be set for the current serial line, i.e. the
- AUX: line. This implies that you have to set the RS232 parameters
- manually for other getty lines. This is because the ATARI Rsconf()
- routine only works for the current line.
- It seems however that this is improved since MINT version 1.08.
- - The UTMP and WTMP entries are only partly filled in.
- Take care: WTMP and BTMP are never truncated, so they grow without bounds.
- - The program checks for the presence of MINT. It can also run under
- normal TOS, but it can only do the most basical things then !
- In this case it can only work with the AUX: line; shells and the
- passwd file must be on drive c: (passwd in /etc)
-
- In your own password file it is important to have passwords with the
- right encryption in your entries, or else you won't be able to login !
- Here I used a (simple) algorithm like EOR with 19+positionnr. , but
- you're free of course to choose your own !
-
- Version 1.1 : Stderr redirection fixed
- (Oct 92) Pid logged in wtmp
- Shell now forks in stead of running as subprocess
- Can also run in background mode without using bg.ttp
- 1.2 : UTMP logging build in.
- 1.3 : Can be used on normal TOS now.
- 1.4 : - SHELL and HOME dir in passwd file can be both in UNIX
- and in TOS notation now.
- - Textfile /etc/welcome will be printed if available
- instead of build in welcome message.
- - Program prints error message now if shell entry
- in passwd could not be started.
- 1.5 : - Getty pid logged in /etc/syslog.
- - Slightly adjusted delay times for modem routines.
- - PURE_C delay function replaced by Delay (modem.c).
- 1.6 : - Multiuser behaviour improved by setting the user and
- group id's before starting a shell.
- - From now on getty can only be run by uid 0 (root).
- - Modem is reset when getty terminates.
- - Extra option (-i) to supply modem init commands from
- the commandline.
-
- Any questions or suggestions about this program can be send to:
- lemmens@dv.twi.tudelft.nl
- */
-
- #ifdef __PUREC__
- #include <tos.h>
- #else
- #include <osbind.h>
- #endif
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
- #include <fcntl.h>
-
- #include "ux_misc.h"
- #include "modem.h"
-
- /* UNIX headers */
-
- #include <utmp.h>
- #include <pwd.h>
- #include <signal.h>
- #include <ioctl.h> /* ioctl and TIOC */
-
- int hwfl,fp,mintflag;
- char *errlog;
- static struct utmp w;
-
- #define MAX_FAIL 4
-
- void sleep(unsigned s);
-
- void LogMsg(char *txt)
- { FILE *log;
- int x;
- time_t tm;
-
- time(&tm);
- for(x=0;x<10 && (log=fopen(errlog,"a")) == NULL;x++)
- sleep(1); /* could be opened by another application */
-
- if(log==NULL) log=stderr;
- fprintf(log,"GETTY (%03d) %.24s: %s\n",Pgetpid(),ctime(&tm),txt);
- if(log != stderr) fclose(log);
- }
-
- void fatal(char *txt)
- { LogMsg(txt);
- exit(1);
- }
-
- void Term_Handler()
- { if(! hwfl) mod_reset();
- fatal("Terminate signal received.");
- }
-
- void log_utmp(struct utmp *w)
- { setutent();
- pututline(w);
- endutent();
- }
-
- void log_xtmp(struct utmp *w,char *file)
- { utmpname(file);
- setutent();
- lseek(utmp_fd,0,SEEK_END); /* goto end of file */
- pututline(w);
- endutent();
- utmpname(UTMP_FILE);
- }
-
- void start_shell(struct passwd *pwent)
- { char shell[100];
- FILE *welcome;
- static char environ[500];
- static char *Badshell ="Problem starting shell !!\r\n";
- static char *WelcomeTxt ="\r\n\nWelcome on ATARI\r\n";
-
- sprintf(shell,"%c:%.97s",mintflag ? 'u' : 'c',
- ux2dos(pwent->pw_shell));
-
- sprintf(environ,"LOGNAME=%s%cHOME=u:%s%cPATH=%s%cTTYNAME=%s",
- pwent->pw_name,0,ux2dos(pwent->pw_dir),0,PATH,0,w.ut_line);
-
- strncpy(w.ut_user,pwent->pw_name,sizeof(w.ut_user));
-
- Fforce(-1,fp); /* redirect terminal to line (Pexec) */
-
- if((welcome = fopen(WELCOME,"r")) != NULL)
- { while(fgets(WelcomeTxt,99,welcome) != NULL)
- Put(WelcomeTxt);
- fclose(welcome);
- }
- else
- Put(WelcomeTxt);
-
- #ifndef DEBUG
-
- if(mintflag)
- { if((w.ut_pid =(int)Pfork()) == 0)
- { /* must change uid & gid in a subprocess or it will
- be impossible to change back to uid 0 again !
- */
- (void)Psetuid(pwent->pw_uid);
- (void)Psetgid(pwent->pw_gid);
- w.ut_pid=Pexec(200,shell," ",environ);
- Put(Badshell); /* only reach this if Pexec overlay fails */
- exit(0);
- }
- }
- w.ut_type=USER_PROCESS;
-
- log_utmp(&w);
- log_xtmp(&w,WTMP_FILE);
-
- if(mintflag)
- Pwait3(0,(long *)0); /* wait for shell to exit */
- else if((w.ut_pid=(int)Pexec(0,shell," ",environ)) < 0)
- Put(Badshell);
-
- #endif
-
- w.ut_type = DEAD_PROCESS;
- log_xtmp(&w,WTMP_FILE);
-
- Fforce(-1,0);
- }
-
- void set_baudrate(int baud)
- { struct sgttyb sg;
- struct { char flag; int rate; }
- t[] = { 0, 0, 7, 300, 8, 600, 9, 1200,
- 11, 2400, 12, 4800, 13, 9600, 14, 19200
- };
- int nr,max=(int)(sizeof(t)/sizeof(t[0]));
-
- for(nr=0;baud != t[nr].rate; nr++)
- if(nr>=max)
- fatal("Unsupported baudrate !");
-
- ioctl(0, TIOCGETP, &sg);
- sg.sg_ispeed = sg.sg_ospeed = t[nr].flag;
- ioctl(0, TIOCSETP, &sg);
- /* With the current driver this can only set AUX: port ! */
- }
-
- int init_modem(int baud,char *cmd)
- { set_baudrate(baud);
- mod_puts(cmd);
- return mod_wait("OK",20,0);
- }
-
- void daemon_mode(void)
- {
- /* if we are the child, kill parent to become a daemon */
- /* proc grp is changed to avoid signal problems (SIGCHLD) */
-
- if(Pfork()) Pwait(); /* wait to be killed !! (gna gna) */
-
- (void)Psetpgrp(0,0);
- (void)Pkill(Pgetppid(),SIGKILL);
- }
-
- void handle_login(void)
- { int cnt;
- struct passwd *pwent;
- char name[50],pwd[50];
- char *lg_txt="\r\nLogin : ";
- char *pw_txt="\r\nPassword: ";
- char *er_txt=" Invalid";
-
- for(cnt=0;cnt<MAX_FAIL;cnt++)
- { do
- { Put(lg_txt);
- while(Cconis()==0)
- sleep(1); /* only to avoid heavy system load */
- Get(name,40,1);
- }while(strlen(name)==0);
-
- Put(pw_txt);
- Get(pwd,40,0);
-
- if((pwent=getpwnam(name)) != NULL)
- if(check_pw(pwd,pwent) >= 0) /* succesfull login */
- { (void)Pnice(-20); /* restore normal priority */
- fflush(stdin);
- start_shell(pwent);
- return; /* force hangup after logout */
- }
- Put(er_txt);
- strncpy(w.ut_name,name,sizeof(w.ut_name));
- w.ut_type=DEAD_PROCESS;
- log_xtmp(&w,BTMP_FILE);
- }
- }
-
- void usage(void)
- { fputs( "\nUsage= getty [-rringcnt] [-iatcmd] [-hwired] "
- "[-daemon] <tty> [<baud>]\n",stderr);
- exit(1);
- }
-
- void main(int argc,char *argv[])
- { static int x,baud,dmfl,uflg;
- char tmpbuf[100];
- char mod_cmd[10]="ats0=1\r\n";
- char *user_cmd=NULL;
- char *connect="CONNECT";
-
- mintflag=RunningMint(); /* look for MiNT cookie */
-
- if(mintflag)
- { if(Pgetuid() != 0)
- { printf("Must have uid 0 !\n");
- exit(1);
- }
- }
- if(argc<2) usage();
-
- errlog=CONSOLE; /* errors by default to console */
- x=argc;
- while(--x>0) /* parse options */
- { if(*argv[1]=='-')
- { switch(*(++argv[1]))
- { case 'h': hwfl=1;
- break; /* hardwired line */
- case 'd': dmfl=1;
- break; /* run in daemonmode */
- case 'r': sprintf(mod_cmd,"ats0=%s\r\n",++argv[1]);
- break; /* nr of rings */
- case 'i': uflg=1;
- user_cmd=++argv[1];
- break;
- default: usage();
- break;
- }
- ++argv; --argc;
- }
- }
-
- if(mk_devnm(tmpbuf,argv[1]) != 0) usage();
-
- if(dmfl && mintflag)
- { daemon_mode(); /* run in background (fork) */
- errlog=SYSLOG;
- }
-
- #ifndef DEBUG
- signal(SIGINT,SIG_IGN); /* ignore Ctrl-C etc. on getty line */
- signal(SIGTERM,Term_Handler);
- #endif
-
- if(mintflag)
- { if((fp = open(tmpbuf,O_RDWR)) < 0)
- fatal("Can't open device !");
- }
- else fp= -2; /* only AUX port under normal TOS */
-
- Fforce(0,fp); /* redirect stdin to line */
- Fforce(1,fp); /* redirect stdout to line */
-
- if(! hwfl) /* use real modem line (AUX) */
- { Fforce(2,fp); /* redirect serial port to line */
- baud = (argc>2 ? atoi(argv[2]) : 0); /* 0 = do not change */
- set_baudrate(baud);
- if(mod_reset() < 0)
- fatal("Modem reset failed !");
- if(init_modem(baud,mod_cmd) < 0)
- fatal("Modem init failed !");
- if(uflg)
- if(init_modem(0,user_cmd) < 0)
- fatal("Modem user cmd failed !");
- }
-
- sprintf(tmpbuf,"Started on %s",argv[1]);
- LogMsg(tmpbuf);
-
- while(1)
- { if(mintflag)
- { (void)Pnice(20);
- w.ut_pid=Pgetpid();
- }
- w.ut_type=LOGIN_PROCESS;
- strncpy(w.ut_line,argv[1],sizeof(w.ut_line));
- strncpy(w.ut_name,"getty",5);
- log_utmp(&w);
-
- if(! hwfl)
- { while(mod_wait(connect,600,0) < 0) /* wait for call */
- { mod_hangup();
- if(init_modem(baud,mod_cmd) < 0) /* restore settings */
- fatal("Proces terminated !");
- }
- mod_gets(tmpbuf,20);
- set_baudrate(atoi(tmpbuf)); /* set new baudrate */
- mod_flush(0);
- }
-
- /* Here we put a prompt on the screen, wait for loginname
- & password and start a shell (or not !)
- */
-
- handle_login();
-
- Put("\r\nHangup\r\n");
- if(hwfl == 0) mod_hangup();
- }
- }
-